package org.fhawk.tinyspring.mvc;

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang.StringUtils;
import org.fhawk.tinyspring.Constant;
import org.fhawk.tinyspring.core.ClassHelper;
import org.fhawk.tinyspring.exception.JvmParnermeterException;
import org.fhawk.tinyspring.ioc.BeanHelper;
import org.fhawk.tinyspring.mvc.bean.Handler;
import org.fhawk.tinyspring.util.ClassUtil;
import org.fhawk.tinyspring.util.ObjectUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 *
 */
public class HandlerHelper {
    private static Logger logger = LoggerFactory.getLogger(HandlerHelper.class);

    private HandlerHelper() {
    }

    public static void invoke(HttpServletRequest request, HttpServletResponse response, Handler handler) throws InvocationTargetException, IllegalAccessException, JvmParnermeterException {
        Class<?> clazz = handler.getTargetClazz();
        Method method = handler.getTargetMethod();
        Object o = BeanHelper.getBean(clazz);
        List<Object> parameters = createParemeters(method, request);
        if (Objects.nonNull(o)) {
            Object result = fileter(request, response);
            if (null == result) {
                result = method.invoke(o, parameters.toArray());
            }
            try {
                request.setCharacterEncoding(Constant.ENCODE);
                response.setCharacterEncoding(Constant.ENCODE);
                response.setHeader("Access-Control-Allow-Origin", "*");
                response.setContentType("application/json");
                String json = JSON.toJSONString(result);
                PrintWriter writer = response.getWriter();
                writer.write(json);
                writer.flush();
                writer.close();
            } catch (IOException e) {
                logger.error("{}:获取 printWriter 失败。",handler);
            }
        } else {
            logger.error("instance of {} can not be found",clazz);
        }
    }

    private static List<Object> createParemeters( Method method, HttpServletRequest request) throws JvmParnermeterException {
        List<Object> values = new ArrayList<>();
        for (Parameter parameter : method.getParameters()) {
            if (parameter.isNamePresent()) {
                logger.error("编译代码必须加上-parameters参数");
                throw new JvmParnermeterException("编译代码必须加上-parameters参数");
            }
            String value = request.getParameter(parameter.getName());
            values.add(StringUtils.isEmpty(value) ? ObjectUtil.newInstance(parameter.getType().getName()) : ClassUtil.castString(value, parameter.getType()));
        }
        return values;
    }

    private static Object fileter(HttpServletRequest request, HttpServletResponse response) {
        List<Class<?>> classList = ClassHelper.getBasePackageClassListBySuperClass(SimpleFilter.class);
        for (Class<?> clazz : classList) {
            Object o = BeanHelper.getBean(clazz);
            if (((SimpleFilter) o).filter(request, response)) {
                return ((SimpleFilter) o).result();
            }
        }
        return null;
    }
}
